<?php
/*
 *  This file is part of Urd.
 *
 *  Urd is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *  Urd is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. See the file "COPYING". If it does not
 *  exist, see <http://www.gnu.org/licenses/>.
 *
 * $LastChangedDate: 2008-06-09 19:13:27 +0200 (Mon, 09 Jun 2008) $
 * $Rev: 1142 $
 * $Author: gavinspearhead $
 * $Id: functions.php 1142 2008-06-09 17:13:27Z gavinspearhead $
 */

if (!defined('ORIGINAL_PAGE')) die('This file cannot be accessed directly.');


$pathwf = realpath(dirname(__FILE__));

require_once "$pathwf/defines.php";
require_once "$pathwf/urdversion.php";
require_once "$pathwf/functions.php";
require_once "$pathwf/autoincludes.php";


function redirect($url, $delay = 0)
{
	assert(is_numeric($delay) && $url != '');
    $output = <<<OUT
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="refresh" content="$delay;url=$url">
</head>
</html>
OUT;
	echo $output;
	exit(NO_ERROR);
}


function post_form($arg, $default='')
{
	assert($arg !== NULL);
	if (array_key_exists($arg, $_POST))
		return addslashes(trim($_POST[$arg]));
	else
		return $default;
}


function get_request($var, $default='')
{
	assert($var !== NULL);
	if (!isset($_REQUEST[$var])) 
		return $default;
	return $_REQUEST[$var];
}


function count_active_ng(DatabaseConnection $db)
{
	$Qsearch = '';
	$sql = " count(*) AS cnt FROM groups WHERE \"active\"='".NG_SUBSCRIBED ."'" ;
	$res = $db->select_query($sql);
	$cnt = $res [0]['cnt'];
	return $cnt;
}


function count_active_rss(DatabaseConnection $db)
{
	$Qsearch = '';
	$sql = " count(*) AS cnt FROM rss_urls WHERE \"subscribed\"='".NG_SUBSCRIBED ."'" ;
	$res = $db->select_query($sql);
	$cnt = $res [0]['cnt'];
	return $cnt;
}


function remove_rss_schedule(DatabaseConnection$db, urdd_client $uc, $id, $cmd)
{
	assert(is_numeric($id));
	$sql = "UPDATE rss_urls SET \"refresh_time\"=0, \"refresh_period\"=0 WHERE \"id\"='$id'";
	$db->execute_query($sql);
	$uc->unschedule(get_command($cmd), $id);
}


function remove_schedule(DatabaseConnection$db, urdd_client $uc, $id, $cmd)
{
	assert(is_numeric($id));
	$sql = "UPDATE groups SET \"refresh_time\"=0, \"refresh_period\"=0 WHERE \"ID\"='$id'";
	$db->execute_query($sql);
	$uc->unschedule(get_command($cmd), $id);
}


function check_urdd_online()
{
    global $db;
    $prefs = load_config($db);
    $uc = new urdd_client($prefs['urdd_host'], $prefs['urdd_port'], 0);
    $status = $uc->can_connect();
    return $status;
}

function stop_urdd()
{
    global $userID, $prefs;
    $uc = new urdd_client($prefs['urdd_host'], $prefs['urdd_port'], $userID);
    if ($uc->is_connected())
        $uc->shutdown();
    usleep(500000);
}


class menu_item 
{
    public $name;
    public $items;
    public $count;
    function __construct(array $items, $name = '')
    {
    //    var_dump($name, $items); echo 
        $this->name = $name;
        $this->items = $items;
        $this->count = count($items);
    }
}


function generate_menu(array $LN)
{
	global $isadmin, $db; // todo

	$do_viewfiles = FALSE; // don't show viewfiles if dbpath isn't set yet
	// Default directory for viewfiles:
	try {
		if (isset($db)) {
			$dlpath = get_dlpath($db);
            if (substr($dlpath, -1, 1) != '/') $dlpath .= '/';
			$do_viewfiles = TRUE;
		}
	} catch (exception $e) {
		$do_viewfiles = FALSE;
	}

	if (isset($_SESSION['urd_username']) && isset($_SESSION['urd_pass'])) 
		$username = $_SESSION['urd_username'];
	else if (isset($_COOKIE['urd_username']) && isset($_COOKIE['urd_pass']))  // it's always in the session but check the cookie anyway
		$username = $_COOKIE['urd_username'];

	$menu = array();

	$item = new menu_item (array('transfers.php' => $LN['menudownloads']));
	$menu[] = $item;

	$item = new menu_item ( array(
			'browse.php' => $LN['menugroupsets'],
			'rsssets.php' => $LN['menursssets']
		), $LN['menubrowsesets']
	);
	$menu[] = $item;

	$item = new menu_item(array(
			'newsgroups.php' => $LN['menunewsgroups'],
			'rssfeeds.php' => $LN['menurssfeeds']
		),$LN['menu_overview']
	);
	$menu[] = $item;
	if ($do_viewfiles === TRUE && isset($username)) {
		$pv_path = urlencode($dlpath . PREVIEW_PATH . $username);
		$done_path = urlencode($dlpath . DONE_PATH . $username);
		$nzb_path = urlencode($dlpath . NZB_PATH . $username); 
		$scripts_path = urlencode($dlpath . SCRIPTS_PATH . $username); 
		$post_path = urlencode($dlpath . POST_PATH . $username); 
		$item = new menu_item (array(
				'viewfiles.php?dir=' . $done_path  => $LN['menuviewfiles_downloads'],
				'viewfiles.php?dir=' . $nzb_path => $LN['menuviewfiles_nzbfiles'],	
				'viewfiles.php?dir=' . $pv_path => $LN['menuviewfiles_previews'],
                'viewfiles.php?dir=' . $scripts_path => $LN['menuviewfiles_scripts'],
				'viewfiles.php?dir=' . $post_path => $LN['menuviewfiles_posts']
			), $LN['menuviewfiles']
		);
		$menu[] = $item;
	}

	$item = new menu_item (array('prefs.php' => $LN['menupreferences']));
	$menu[] = $item;

	$item =new  menu_item(array('stats.php' => $LN['menustats']));
	$menu[] = $item;
	if (isset($isadmin) && $isadmin) {
		$item = new menu_item(array(
				'admin_config.php'=> $LN['menuadminconfig'],
				'admin_usenet_servers.php'=> $LN['menuadminusenet'],
				'admin_control.php' => $LN['menuadmincontrol'],
				'admin_tasks.php' => $LN['menuadmintasks'],
				'admin_jobs.php' => $LN['menuadminjobs'],
				'admin_users.php' => $LN['menuadminusers'],
				'admin_buttons.php' => $LN['menuadminbuttons'],
				'admin_log.php' => $LN['menuadminlog']
            ),$LN['menuadmin']
        );
		$menu[] = $item;
	}

	$item = new menu_item(array(
			'manual.php' => $LN['menumanual'], 
			'faq.php' => $LN['menufaq'],
			'about.php' => $LN['menuabout'],
			'licence.php' => $LN['menulicence'],
			'http://urdland.com/forum/' => $LN['menuforum'],
			'debug.php' => $LN['menudebug']
		), $LN['menuhelp'] 
	);
	$menu[] = $item;

	if (isset($username)){
		$item = new menu_item (array('logout.php'  => $LN['menulogout'] . '(' .htmlentities($username) . ')'));
		$menu[] = $item;
	} else {
		$item = new menu_item (array('login.php' => $LN['menulogin']));
		$menu = array ($item);
	}
	return $menu;
}


function verify_challenge_text($c1)
{ 
	global $LN;
	if (!isset ($_SESSION['challenge']) || $c1 != $_SESSION['challenge'] || $_SESSION['challenge_timeout'] < time()){
		die_html($LN['error_invalidchallenge2']);
	}
}


function verify_challenge($c1)
{ 
	global $LN;
	if (!isset ($_SESSION['challenge']) || $c1 != $_SESSION['challenge'] || $_SESSION['challenge_timeout'] < time()){
		semi_fatal_error($LN['error_invalidchallenge']);
	}
}


function set_challenge()
{
	if (!isset ($_SESSION['challenge']) || ($_SESSION['challenge_timeout']) < (time() )) { // if the challenge is valid for less than a minute we get a new one
		$challenge = generate_password(CHALLENGE_LENGTH);
		$_SESSION['challenge'] = $challenge;
		$_SESSION['challenge_timeout'] = time() + CHALLENGE_TIMEOUT;
	} else 
		$challenge = $_SESSION['challenge'];
	return $challenge;
}


function command_description(DatabaseConnection$db, $task)
{
    try {

        global $LN;
        $isCheckVersion = $isCleandir = $isCleandb = $isExpire = $isUpdate = $isPurge = $isDownload = $isGroups = $isMakenzb = FALSE;
        $isSendSetInfo = $isGetSetInfo = $isUnParRar = $isOptimise = $isUpdateRss = $isPurgeRss = $isExpireRss = FALSE;
        $isGenSets = $isAddData = $isMergeSets = $isFindServers = $isParseNzb = $isDeleteSet = $isDeleteSetRss = $isPost = FALSE;

        if (stripos($task, get_command(COMMAND_UPDATE) . ' ') === 0) 			$isUpdate = TRUE;
        else if (stripos($task, get_command(COMMAND_PURGE) . ' ') === 0) 		$isPurge = TRUE;
        else if (stripos($task, get_command(COMMAND_EXPIRE) . ' ') === 0) 		$isExpire = TRUE;
        else if (stripos($task, get_command(COMMAND_PARSE_NZB) . ' ') === 0) 		$isParseNzb = TRUE;
        else if (stripos($task, get_command(COMMAND_UPDATE_RSS) . ' ') === 0) 		$isUpdateRss = TRUE;
        else if (stripos($task, get_command(COMMAND_PURGE_RSS) . ' ') === 0) 		$isPurgeRss = TRUE;
        else if (stripos($task, get_command(COMMAND_EXPIRE_RSS) . ' ') === 0) 		$isExpireRss = TRUE;
        else if (stripos($task, get_command(COMMAND_DOWNLOAD) . ' ') === 0) 		$isDownload = TRUE;
        else if (stripos($task, get_command(COMMAND_DOWNLOAD_ACTION) . ' ') === 0) 	$isDownload = TRUE;
        else if (stripos($task, get_command(COMMAND_GROUPS)) === 0) 			$isGroups = TRUE;
        else if (stripos($task, get_command(COMMAND_UNPAR_UNRAR)) === 0) 		$isUnParRar = TRUE;
        else if (stripos($task, get_command(COMMAND_OPTIMISE)) === 0) 			$isOptimise = TRUE;
        else if (stripos($task, get_command(COMMAND_CLEANDB)) === 0) 			$isCleandb = TRUE;
        else if (stripos($task, get_command(COMMAND_CLEANDIR)) === 0) 			$isCleandir = TRUE;
        else if (stripos($task, get_command(COMMAND_CHECK_VERSION)) === 0) 		$isCheckVersion = TRUE;
        else if (stripos($task, get_command(COMMAND_SENDSETINFO)) === 0) 		$isSendSetInfo = TRUE;
        else if (stripos($task, get_command(COMMAND_GETSETINFO)) === 0) 			$isGetSetInfo = TRUE;
        else if (stripos($task, get_command(COMMAND_GENSETS)) === 0) 			$isGenSets = TRUE;
        else if (stripos($task, get_command(COMMAND_ADDDATA)) === 0) 			$isAddData = TRUE;
        else if (stripos($task, get_command(COMMAND_MERGE_SETS)) === 0) 			$isMergeSets = TRUE;
        else if (stripos($task, get_command(COMMAND_FINDSERVERS)) === 0) 			$isFindServers = TRUE;
        else if (stripos($task, get_command(COMMAND_DELETE_SET)) === 0) 			$isDeleteSet = TRUE;
        else if (stripos($task, get_command(COMMAND_POST)) === 0) 			$isPost = TRUE;
        else if (stripos($task, get_command(COMMAND_MAKE_NZB)) === 0) 			$isMakenzb = TRUE;
        else if (stripos($task, get_command(COMMAND_START_POST)) === 0) 			$isPost = TRUE;
        else if (stripos($task, get_command(COMMAND_POST_ACTION)) === 0) 			$isPost = TRUE;
        else if (stripos($task, get_command(COMMAND_DELETE_SET_RSS)) === 0) 			$isDeleteSetRss = TRUE;

        // For tasks that end with a groupID:
        if ($isPurge || $isUpdate || $isExpire || $isGenSets) {
            $tmp = explode(' ', $task);
            $groupID = $tmp[count($tmp)-1];
            $isPurge   ? $task = $LN['taskpurge'] : 1;
            $isUpdate  ? $task = $LN['taskupdate'] : 1;
            $isExpire  ? $task = $LN['taskexpire'] : 1;
            $isGenSets ? $task = $LN['taskgensets'] : 1;
            if (is_numeric($groupID)) {
                $db->escape($groupID, TRUE);
                $sql = "\"name\" FROM groups WHERE \"ID\" = $groupID";
                $res = $db->select_query($sql, 1);
                if ($res !== FALSE)
                    $task .= ' [b]' . htmlentities($res[0]['name']) . '[/b]';
            }
        } elseif ($isPurgeRss || $isUpdateRss || $isExpireRss) {
            $isPurgeRss  ? $feed_id = str_ireplace(get_command(COMMAND_PURGE_RSS) . ' ', '', $task) : 1;
            $isUpdateRss ? $feed_id = str_ireplace(get_command(COMMAND_UPDATE_RSS) . ' ', '', $task) : 1;
            $isExpireRss ? $feed_id = str_ireplace(get_command(COMMAND_EXPIRE_RSS) . ' ', '', $task) : 1;
            $isPurgeRss  ? $task = $LN['taskpurge'] : 1;
            $isUpdateRss ? $task = $LN['taskupdate'] : 1;
            $isExpireRss ? $task = $LN['taskexpire'] : 1;
            $db->escape($feed_id, TRUE);
            $sql = "\"name\" FROM rss_urls WHERE \"id\" = $feed_id";
            $res = $db->select_query($sql, 1);
            $task .= ' [b]' . htmlentities($res[0]['name']) . '[/b]';
        } elseif ($isGroups) {
            $task = $LN['cmd_descr_dlng'];
        } elseif ($isPost) {
            $id = str_ireplace(get_command(COMMAND_POST_ACTION) . ' ', '', $task); 
            $id = str_ireplace(get_command(COMMAND_START_POST) . ' ', '', $id); 
            $id = str_ireplace(get_command(COMMAND_POST) . ' ', '', $id); 
            $name = get_post_name($db, $id);
            $task = $LN['cmd_descr_post'] . ' ' ;
            $task .= '[b]' . htmlentities($name) . '[/b]';
        } elseif ($isOptimise) {
            $task = $LN['cmd_descr_optdb'] 	;
        } elseif ($isCleandb) {
            $task = $LN['cmd_descr_cleandb']; 
        } elseif ($isCheckVersion) {
            $task = $LN['cmd_descr_checkvrs'];
        } elseif ($isSendSetInfo) {
            $task = $LN['cmd_descr_sendsetinfo'];
        } elseif ($isGetSetInfo) {
            $task = $LN['cmd_descr_getsetinfo'];
        } elseif ($isMergeSets) {
            $task = $LN['cmd_descr_mergesets'];
        } elseif ($isFindServers) {
            $task = $LN['cmd_descr_findservers'];
        } elseif ($isParseNzb) {
            $task = $LN['cmd_descr_parsenzb'];
        } elseif ($isDeleteSet) {
            $ids = str_ireplace(get_command(COMMAND_DELETE_SET) . ' ', '', $task); 
            $task = $LN['cmd_descr_deleteset'] . ' ' . $ids;
        } elseif ($isDeleteSetRss) {
            $ids = str_ireplace(get_command(COMMAND_DELETE_SET_RSS) . ' ', '', $task); 
            $task = $LN['cmd_descr_deleteset']. ' '  . $ids;
        } elseif ($isCleandir) {
            $dir = str_ireplace(get_command(COMMAND_CLEANDIR) . ' ', '', $task); 
            $task = $LN['cmd_descr_cleandir'] . ' '  . htmlentities($dir);
        } elseif ($isDownload) {
            $ID = str_ireplace(get_command(COMMAND_DOWNLOAD_ACTION) . ' ', '', $task);
            $ID = str_ireplace(get_command(COMMAND_DOWNLOAD) . ' ', '', $ID);
            $task = $LN['cmd_descr_dl'] .' ';
            $name = htmlentities(get_download_name($db, $ID));
            $task .= '[b]' . htmlentities( $name) . '[/b]';
        } elseif ($isUnParRar) {
            $tmp = explode(' ', $task);
            $upr = $tmp[count($tmp)-2];
            $ID = $tmp[count($tmp)-1];
            $task = '';
            if ($upr & DO_UNPAR) $task .= 'Unpar ';
            if ($upr & DO_UNRAR) $task .= 'Unrar ';
            $name = htmlentities(get_download_name($db, $ID));
            $task .= '[b]' . htmlentities($name) . '[/b]';
        } elseif ($isMakenzb) {
            $tmp = explode(' ', $task);
            $ID = $tmp[1];
            $name = htmlentities(get_download_name($db, $ID));
            $task = $LN['taskmakenzb'] . ' [b]' . $name . '[/b]';
        } elseif ($isAddData) {
            $tmp = explode(' ', $task);
            $ID = $tmp[1];
            $preview = $tmp[count($tmp)-1];
            $preview = ($preview == 'preview') ? TRUE : FALSE;
            if ($preview) {
                $name = 'preview ' . $ID;
            } else {
                $name = htmlentities(get_download_name($db, $ID));
            }
            $task = $LN['taskadddata'] . ' [b]' . $name . '[/b]';
        }
        return $task;
    } catch (exception $e) {
        return '';
    }
}


function get_maxperpage(DatabaseConnection $db, $userID)
{
	assert(is_numeric($userID));
	$db->escape($userID, TRUE);
	$query = "SELECT \"value\" FROM preferences WHERE \"userID\" = $userID AND \"option\"='setsperpage'";
	$res = $db->execute_query($query);
	if ($res === FALSE)
		return DEFAULT_PER_PAGE;
	else 
		return $res[0]['value'];
}


function get_languages()
{
	global $langdir;
	$l = glob($langdir . '*.php');
	$langs = array();
	foreach ($l as $lang) {
		if (strcasecmp (basename ($lang), 'index.php') == 0) 
			continue;
		$k = basename($lang);
		$v = ucfirst(basename($lang, '.php'));
		$langs[$k] = $v;
	}
	return $langs;
}


function select_language(DatabaseConnection $db, $userID)
{
	$language = NULL;
	if ($userID !== NULL) {
		try {
			$language = get_pref($db, 'language', $userID);
		} catch (exception $e) {
		}
	}

	if ($language === NULL) {
		try {
			$language = get_config($db, 'default_language');
		} catch (exception $e) {
			$language = NULL;
		}
	}
	return $language;
}	


function get_templates()
{
	global $tpldir;
	$t = glob($tpldir . '*', GLOB_ONLYDIR|GLOB_MARK);
	$tpls = array();
	foreach ($t as $tpl) {
		$bn = basename($tpl);
		if ($bn[0] == '.') 
			continue;
		$k = $bn;
		$v = ucfirst($bn);
		$tpls[$k] = $v;
	}
	return $tpls;
}


function select_template(DatabaseConnection $db, $userID)
{
	$template = NULL;
	if ($userID !== NULL) {
		try {
			$template = get_pref($db, 'template', $userID);
		} catch (exception $e) {
	//		$template = NULL;
		}
	}
	if ($template === NULL) {
		try {
			$template = get_config($db, 'default_template');
		} catch (exception $e) {
			$template = NULL;
		}
	}
	return $template;
}


function get_buttons(DatabaseConnection $db)
{
	$qry_b = 'SELECT * FROM searchbuttons';
	$res_b = $db->execute_query($qry_b);
	if ($res_b === FALSE) 
		$res_b = array();

	$searchbuttons = array(); 
	foreach ($res_b as $row) 
		$searchbuttons[$row['id']] = $row['name'];
	return $searchbuttons;
}


function process_schedule (urdd_client $uc, $period, $time1, $time2, $command, $arg_unschedule, $arg_schedule)
{
	assert(is_numeric($period) && is_numeric($time1) && is_numeric($time2));
	global $periods;

	$period = $periods->get($period);
	$period_hours = $period->interval;
	$time = $time1 * 60 + $time2;
	$nicetime = $time1 . ':' . $time2;
	$next = $period->next . ' ' . $nicetime;
	$uc->unschedule(get_command($command), $arg_unschedule);
	$resp = $uc->schedule(get_command($command), $arg_schedule, $next, $period_hours * 3600);
	return $resp;
}


function generate_set_info(array $extsetinfo)
{
	global $LN;
	// This function determines what extsetinfo can be created for a set. Used for editing sets manually.

	// Generic fields:
	$fields = array('name');
	$addfields = array();

	// What fields do we show? Depends on the type of file. What files are there? Do we put it in the db or hardcode it?
	// Questions, questions! Let's start by hardcoding it for now.
	switch ($extsetinfo['binarytype']) {
		case SETTYPE_MOVIE :       $addfields = array('year', 'quality', 'score', 'movieformat', 'lang', 'sublang', 'audioformat', 'moviegenre', 'link', 'xrated', 'note'); break;
		case SETTYPE_ALBUM :       $addfields = array('year', 'quality', 'score', 'musicformat', 'musicgenre', 'link', 'xrated', 'note'); break;
		case SETTYPE_IMAGE :       $addfields = array('quality', 'imageformat', 'imagegenre', 'xrated', 'note'); break;
		case SETTYPE_SOFTWARE :    $addfields = array('quality', 'os', 'softwareformat', 'softwaregenre', 'lang', 'xrated', 'note'); break;
		case SETTYPE_TVSERIES :    $addfields = array('quality', 'score', 'movieformat', 'moviegenre', 'audioformat', 'episode', 'link', 'xrated', 'note'); break;
		case SETTYPE_EBOOK :       $addfields = array('author', 'quality', 'ebookformat', 'genericgenre'); break;
		case SETTYPE_TVSHOW :      $addfields = array('quality', 'score', 'movieformat', 'moviegenre', 'audioformat', 'episode', 'link', 'xrated', 'note'); break;
		case SETTYPE_DOCUMENTARY : $addfields = array('year', 'quality', 'score', 'movieformat', 'lang', 'sublang', 'audioformat', 'link', 'xrated', 'note'); break;
		case SETTYPE_GAME :        $addfields = array('quality', 'os', 'gameformat', 'gamegenre', 'lang', 'xrated', 'note'); break;
		case SETTYPE_OTHER :       $addfields = array('quality', 'genericgenre', 'xrated', 'note'); break;
		case SETTYPE_UNKNOWN :     break;
	}

	// Add extra fields regardless of type:
	$addfields[] = 'password';
	$addfields[] = 'copyright';

	// Combine:
	$fields = array_merge($fields,$addfields);
	// Order is important because it determines the order in which the fields are displayed when editing...


	// Example values:
	$rating = array('');
	for ($x = 1; $x <= 10; $x+=0.5)	
		$rating[] = $x;

	$movieformat = array('',  '720p', '1080i', '1080p', 'xvid', 'divx', 'bluray', 'avi', 'mpg', 'mov', 'wmv', 'black/white', 'H.264', 'dvd', 'vhs', 'other');
	$audioformat = array('', 'mono', 'stereo', 'Dolby Digital', 'DTS', 'other');
	$musicformat = array('', 'mp3', 'ogg', 'wma', 'ape', 'wav', 'flac', 'mpc', 'other');
	$imageformat = array('', 'jpg', 'png', 'bmp', 'psd', 'gif', 'raw', 'tiff', 'svg', 'other');
	$softwareformat = array('', 'iso', 'bin', 'zip', 'exe', 'msi', 'source', 'rpm', 'deb', 'rar', '7z', 'arc', 'zoo', 'arj', 'lha', 'other');
	$gameformat = array('', 'iso', 'bin', 'zip', 'exe', 'msi', 'source', 'rpm', 'deb', 'rar', '7z', 'arc', 'zoo', 'arj', 'lha', 'other');
	$ebookformat = array('', 'txt', 'lit', 'pdf', 'html', 'audio', 'other');
	$os = array('', 'winall', 'windows', 'windows 64bit', 'windows mobile', 'linux', 'macos', 'bsd', 'symbian', 'iphone', 'android', 'os-independent', 'xbox', 'playstation', 'wii', 'other');

	$display = array();
	foreach ($fields as $field) {
		$displaytype = $edittype = $editvalues = '';

		switch ($field) {
			case 'name':		$displaytype = 'text';		$edittype = 'longtext';						break;
			case 'artist':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'author':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'lang':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'sublang':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'quality':		$displaytype = 'number';	$edittype = 'select';		$editvalues = $rating;		break;
			case 'movieformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $movieformat;	break;
			case 'musicformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $musicformat;	break;
			case 'imageformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $imageformat;	break;
			case 'softwareformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $softwareformat;	break;
			case 'audioformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $audioformat;	break;
			case 'ebookformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $ebookformat;	break;
			case 'gameformat':	$displaytype = 'text';		$edittype = 'select';		$editvalues = $gameformat;	break;
			case 'moviegenre':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'gamegenre':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'musicgenre':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'softwaregenre':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'os':		$displaytype = 'text';		$edittype = 'select';		$editvalues = $os;		break;
			case 'year':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'genericgenre':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'episode':		$displaytype = 'text';		$edittype = 'text';						break;
			case 'score':		$displaytype = 'number';	$edittype = 'select';		$editvalues = $rating;		break;
			case 'link':		$displaytype = 'url';		$edittype = 'longtext';						break;
			case 'xrated':		$displaytype = 'checkbox';	$edittype = 'checkbox';						break;
			case 'copyright':	$displaytype = 'checkbox';	$edittype = 'checkbox';						break;
			case 'password':	$displaytype = 'text';		$edittype = 'text';						break;
			case 'note':		$displaytype = 'text';		$edittype = 'longtext';						break;
			default:		$displaytype = 'text';		$edittype = 'text';
		}

		$value = isset($extsetinfo[$field]) ? $extsetinfo[$field] : '';

		$display[] = array(	
			'field' => $field,
			'name' => $LN['browse_tag_' . $field],
			'value' => $value,
			'edit' => $edittype,
			'display' => $displaytype,
			'editvalues' => $editvalues);
	}
	return $display;
}


function get_binary_types()
{
	global $LN;

	$binarytypes = array(	
		SETTYPE_UNKNOWN 	=> $LN['bin_unknown'],
		SETTYPE_MOVIE		=> $LN['bin_movie'],
		SETTYPE_ALBUM 		=> $LN['bin_album'],
		SETTYPE_IMAGE 		=> $LN['bin_image'],
		SETTYPE_SOFTWARE 	=> $LN['bin_software'],
		SETTYPE_TVSERIES 	=> $LN['bin_tvseries'],
		SETTYPE_EBOOK	 	=> $LN['bin_ebook'],
		SETTYPE_GAME	 	=> $LN['bin_game'],
		SETTYPE_DOCUMENTARY	=> $LN['bin_documentary'],
		SETTYPE_TVSHOW	 	=> $LN['bin_tvshow'],
		SETTYPE_OTHER 		=> $LN['bin_other']
	);
	return $binarytypes;
}


function create_extset_download_name(DatabaseConnection $db, $setID)
{
	$db->Escape($setID);
	$sql = "SELECT * FROM extsetdata WHERE \"setID\" = '" . $setID . "'";
	$res = $db->execute_query($sql);
	if ($res === FALSE)
		return FALSE;

	// Initialise and store extsetdata in $value
	$value = array();

	foreach ($res as $row)
		$value[$row['name']] = $row['value'];

	// Create a downloadname based on the type of binary:
	$downloadname = '';
	switch($value['binarytype']) {
		case SETTYPE_MOVIE:
			if (isset($value['name'])) $downloadname .= $value['name'];
			if (isset($value['year'])) $downloadname .= ' (' . $value['year'] . ')';
			if (isset($value['movieformat'])) $downloadname .= ' [' . $value['movieformat'] . ']';
			break;
		case SETTYPE_TVSERIES:
			if (isset($value['name'])) $downloadname .= $value['name'];
			if (isset($value['episode'])) $downloadname .= ' ' . $value['episode'];
			if (isset($value['movieformat'])) $downloadname .= ' [' . $value['movieformat'] . ']';
			break;
		default:
			$downloadname = (isset($value['name'])) ? $value['name'] : 'missing name ' . $setID;
	}
	return sanitise_download_name($db, $downloadname);
}


function thisornothing($var)
{
	if (isset($var)) 
		return $var;
}


function generate_nzb_from_set(DatabaseConnection $db, array $selected) 
{
	$str = '<' . '?' . 'xml version="1.0" encoding="us-ascii"' . '?' . '>' . "\n"; // screws up syntax highlighting... hence the wacky sequence of < and ? and ? and > ... DO NOT CHANGE!
	$str .= '<!DOCTYPE nzb PUBLIC "-//newzBin//DTD NZB 1.0//EN" "http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd">'. "\n";
	$str .= '<nzb xmlns="http://www.newzbin.com/DTD/2003/nzb">' . "\n";
	$str .= "<!-- Created by URD : www.urdland.com : The web-based usenet resource downloader. -->\n";

	if(count($selected) == 0)
		return $str . $LN['error_nosetids'] ;

	foreach ($selected as $setID) {
		$sql = "SELECT \"groupID\" FROM \"setdata\" WHERE \"ID\" = '$setID'";
		$res = $db->execute_query($sql);
		if ($res === FALSE) continue;
		$groupID = $res[0]['groupID'];

		$sql = "SELECT *, \"date\" AS unixdate FROM binaries_{$groupID} WHERE \"setID\" = '$setID' ORDER BY \"subject\"";
		$res = $db->execute_query($sql);
		$res2 = $db->execute_query("SELECT \"name\" FROM groups WHERE \"ID\" = '{$groupID}'");
		if ($res === FALSE || $res2 === FALSE) continue;
		$group = $res2[0]['name'];

		foreach ($res as $arr) {
			$name = preg_replace("/[^a-zA-Z0-9\(\)\! .]/", '', str_replace('"', '', $arr['subject']));
			$arr['fromname'] = str_replace('(', '', str_replace(')', '', $arr['fromname']));
			$str .= "\t<file poster=\"who@no.com\" date=\"{$arr['unixdate']}\" subject=\"$name (1/{$arr['totalParts']})\">\n";
			$str .= "\t<groups>\n";
			$str .= "\t\t<group>{$group}</group>\n";
			$str .= "\t</groups>\n";
			$str .= "\t<segments>\n";
			$res2 = $db->execute_query("SELECT * FROM \"parts_$groupID\" WHERE \"binaryID\" = '{$arr['binaryID']}' ORDER BY \"partnumber\"");
			if ($res2 === FALSE) $res2 = array();
			foreach ($res2 as $arr2) {
				$arr2['messageID'] = str_replace('&', '&amp;', $arr2['messageID']);
				$str .= "\t\t<segment bytes=\"{$arr2['size']}\" number=\"".round($arr2['partnumber'])."\">{$arr2['messageID']}</segment>\n";
			}
			$str .= "\t</segments>\n";
			$str .= "\t</file>\n";
		}
	}
	$str .= '</nzb>';
	return $str;
}


function start_preview(DatabaseConnection $db, $pbin_id, $pgroup_id, $user_id)
{
	global $rprefs, $LN;

	$sql = "SELECT \"subject\", \"bytes\" FROM binaries_$pgroup_id WHERE \"binaryID\" = '$pbin_id'";
	$res0 = $db->execute_query($sql);
	$dlname = $res0[0]['subject']; 
	$size = $res0[0]['bytes']; 
	if ($size > MAX_PREVIEW_SIZE)
		throw new exception($LN['error_preview_size_exceeded']);

	$uc = new urdd_client($rprefs['urdd_host'], $rprefs['urdd_port'], $user_id);

	if (!$uc->is_connected()) 
		throw new exception($LN['error_urddconnect']);

	// Create download:
	$result = $uc->create_preview();
	if ($result === FALSE) 
		throw new exception($LN['error_createdlfailed'] );
	$result = $uc->decode($result);

	// Download ID:
	$dlid = $result[0];
	$dlthreads = $result[1];
	$status = DOWNLOAD_READY;
	$dlname = find_name($db, $dlname);
	$max_dl_name = get_config($db, 'max_dl_name');
	$dlname = substr($dlname, 0, $max_dl_name); // DL names are no longer than X characters when auto-generated

	set_download_name($db, $dlid, $dlname);
	set_download_size($db, $dlid, $size);
	$uc->add_bin_data($dlid, $pgroup_id, $pbin_id, TRUE);

	add_stat_data($db, STAT_ACTION_PREVIEW, $size, $user_id);
	
	foreach ($dlthreads as $id)
		$uc->unpause($id);

	return $dlid;
}


function create_download(DatabaseConnection $db, $userID)
{
	global $LN;
	$rprefs = load_config($db);
	if (isset($_POST['timestamp']) && $_POST['timestamp'] != '') {
		$timestamp = $_POST['timestamp'];
		$time_int = strtotime($timestamp);
		if ($time_int === FALSE) {
			$timestamp = NULL;
			near_fatal_error($LN['browse_invalid_timestamp'], 'timestamp', NULL);
		} else if ($time_int < time()) { // the time is before now, so probably means tomorrow 
			$time_int += 24 * 60 * 60; // next day
			$timestamp .= ' +1 day';
		}
	} else 
		$timestamp = NULL;
	$uc = new urdd_client($rprefs['urdd_host'], $rprefs['urdd_port'], $userID);

	if (!$uc->is_connected()) 
		throw new exception($LN['error_urddconnect']);

	$total_size = 0;
	foreach ($_SESSION['setdata'] as $set) {
		$setID = $set['setid'];
		$type = $set['type'];
		if ($type == 'group') {
			$res = $db->execute_query("SELECT size FROM setdata WHERE \"ID\" = '$setID'");
			if($res === FALSE) 
				throw new exception($LN['error_invalidsetid']);

		} else if ($type == 'rss'){
			$res = $db->execute_query("SELECT size FROM rss_sets WHERE \"setid\" = '$setID'");
			if($res === FALSE) 
				throw new exception($LN['error_invalidsetid']);
		}

		$total_size += $res[0]['size'];
	}
	$disk_space = $uc->diskfree('b');
	if ($disk_space[0] < (2.5* $total_size) && !isset($_POST['ignore_diskfull'])) 
		near_fatal_error($LN['error_diskfull'], 'ignore_diskfull', 'diskfull');

	// Create download:
	$result = $uc->create_download();
	if ($result === FALSE) 
		throw new exception($LN['error_createdlfailed']);
	$result = $uc->decode($result);

	// Download ID:
	$dlid = $result[0];
	$dlthreads = $result[1];

	// name | unpar | unrar | status | destination | username  |
	$firstSetID = $_SESSION['setdata'][0]['setid'];
	$first_type = $_SESSION['setdata'][0]['type'];
	$db->escape($firstSetID);
	if ($first_type == 'group') {
		$sql = 'SELECT setdata."subject", extsetdata."value" FROM ' 	. 
		"(setdata LEFT JOIN extsetdata ON setdata.\"ID\" = extsetdata.\"setID\" AND extsetdata.\"name\" = 'name') " . 
		"WHERE \"ID\" = '$firstSetID' ";
	} else if($first_type == 'rss') {
		$sql = 'SELECT rss_sets."setname" AS "subject", extsetdata."value" FROM ' 	. 
		"(rss_sets LEFT JOIN extsetdata ON rss_sets.\"setid\" = extsetdata.\"setID\" AND extsetdata.\"name\" = 'name') " . 
		"WHERE rss_sets.\"setid\" = '$firstSetID' ";
	} else 
		throw new exception ('Unknown type: ' . $first_type);
	$res0 = $db->execute_query($sql);
	// Is there an extset setname? If so, use it, else use the autogenerated setname
	if (isset($_POST['dlsetname']))
		$dlname = trim($_POST['dlsetname']);
	if ($dlname == '') {
		if ($res0[0]['value'] != '') { 
			$dlname = create_extset_download_name($db, $firstSetID);
		} else {
			$dlname = $res0[0]['subject']; 
			$dlname = find_name($db, $dlname);
		}
	}

	$max_dl_name = get_config($db, 'max_dl_name');
	$dlname = substr($dlname, 0, $max_dl_name); // DL names are no longer than X characters when auto-generated
	set_download_name($db, $dlid, $dlname);

	// Keep track of total downloadsize:
	foreach ($_SESSION['setdata'] as $set) {
		$setid = $set['setid'];
		$type = $set['type'];
		if ($type == 'group') {
			$type_val = USERSETTYPE_GROUP;
			$uc->add_set_data($dlid, $setid);
			// Mark as read:
		} else if ($type = 'rss') {
			$type_val = USERSETTYPE_RSS;
			$sql = "SELECT nzb_link FROM rss_sets WHERE \"setid\" = '$setid'";
			$res = $db->execute_query($sql);
			if ($res !== FALSE) {
				$url = $res[0]['nzb_link'];
				$uc->parse_nzb($url, $dlid); 
				// mark user info
			} else
				throw new exception('cannot get rss info');

		} else {
			throw new exception ('Unknown type: ' .$type);
		}
		$res = $db->execute_query("SELECT * FROM usersetinfo WHERE \"userID\" = '$userID' AND \"setID\" = '$setid' AND \"type\"='" . $type_val . "'");
		if ($res === FALSE)
			$qry = "INSERT INTO usersetinfo (\"setID\", \"userID\", \"statusread\", \"type\") VALUES ('$setid', '$userID', '" . MARKING_ON . "', '" . $type_val . "')";
		else
			$qry = "UPDATE usersetinfo SET \"statusread\" = 1 WHERE \"setID\" = '$setid' AND \"userID\" = '$userID' AND \"type\"='" . $type_val . "'";
		$db->execute_query($qry);
	}

	// Store size:
	set_download_size($db, $dlid, $total_size);

	$stat_id = add_stat_data($db, STAT_ACTION_DOWNLOAD, 0, $userID); // fix stats
	set_stat_id($db, $dlid, $stat_id);
	foreach ($dlthreads as $id) {
		if ($timestamp === NULL){ // if no timestamp is given, just start it
			usleep(500000);
			set_start_time($db, $dlid, time());
			$uc->unpause($id);
		} else { // otherwise schedule a continue command @ a given time
			set_start_time($db, $dlid, $time_int);
			$uc->schedule(get_command(COMMAND_CONTINUE),  '"' . get_command(COMMAND_DOWNLOAD) . ' ' .  $dlid . '"' , $timestamp);
		}
	}

	$_SESSION['setdata'] = array();
	unset ($_SESSION['dlsetname']) ;
	return ''; 
}


function create_nzb(DatabaseConnection $db, $userID)
{
	global $LN;
	$rprefs = load_config($db);
	$uc = new urdd_client($rprefs['urdd_host'], $rprefs['urdd_port'], $userID);

	if (!$uc->is_connected()) 
		throw new exception($LN['error_urddconnect']);

	$result = $uc->make_nzb();
	if ($result === FALSE) 
		throw new exception($LN['error_createdlfailed']);
	$result = $uc->decode($result);

	// Download ID:
	$dlid = $result[0];
	$dlthreads = $result[1];

	$firstSetID = $_SESSION['setdata'][0]['setid'];
	$first_type = $_SESSION['setdata'][0]['type'];

	$db->escape($firstSetID);
	if ($first_type == 'group') {
		$sql = 'SELECT setdata."subject", extsetdata."value" FROM ' 	. 
		"(setdata LEFT JOIN extsetdata ON setdata.\"ID\" = extsetdata.\"setID\" AND extsetdata.\"name\" = 'name') " . 
		"WHERE \"ID\" = '$firstSetID' ";
	} else if($first_type == 'rss') {
		$sql = 'SELECT rss_sets."setname" AS "subject", extsetdata."value" FROM ' 	. 
		"(rss_sets LEFT JOIN extsetdata ON rss_sets.\"setid\" = extsetdata.\"setID\" AND extsetdata.\"name\" = 'name') " . 
		"WHERE rss_sets.\"setid\" = '$firstSetID' ";
	} else 
			throw new exception ('unknown type: ' . $first_type);

	$res0 = $db->execute_query($sql);
	if (isset($_POST['dlsetname']))
		$dlname = trim($_POST['dlsetname']);
	if ($dlname == '') {
		// Is there an extset setname? If so, use it, else use the autogenerated setname
		if ($res0[0]['value'] != '') { 
			$dlname = create_extset_download_name($db, $firstSetID);
		} else {
			$dlname = $res0[0]['subject']; 
			$dlname = find_name($db, $dlname);
		}
	}

	$max_dl_name = get_config($db, 'max_dl_name');
	$dlname = substr($dlname, 0, $max_dl_name); // DL names are no longer than X characters when auto-generated
	set_download_name($db, $dlid, $dlname);
	foreach ($_SESSION['setdata'] as $set) {
		$setid = $set['setid'];
		$type = $set['type'];
		if ($type == 'group') {
			$type_val = USERSETTYPE_GROUP;
			$uc->add_set_data($dlid, $setid);
		} else if ($type = 'rss') {
			$type_val = USERSETTYPE_RSS;
			$sql = "SELECT nzb_link FROM rss_sets WHERE \"setid\" = '$setid'";
			$res = $db->execute_query($sql);
			if ($res !== FALSE) {
				$url = $res[0]['nzb_link'];
				$uc->parse_nzb($url, $dlid); 
			} else
				throw new exception('cannot get rss info');
		} else
			throw new exception('cannot get rss info');
		$res = $db->execute_query("SELECT * FROM usersetinfo WHERE \"userID\" = '$userID' AND \"setID\" = '$setid' AND \"type\"='" . $type_val . "'");
		if ($res === FALSE)
			$qry = "INSERT INTO usersetinfo (\"setID\", \"userID\", \"statusnzb\", \"type\") VALUES ('$setid', '$userID', '" . MARKING_ON . "', '" . $type_val . "')";
		else
			$qry = "UPDATE usersetinfo SET \"statusnzb\" = 1 WHERE \"setID\" = '$setid' AND \"userID\" = '$userID' AND \"type\"='" . $type_val . "'";
		$db->execute_query($qry);

	}
	foreach ($dlthreads as $id) {
		usleep(500000);
		set_start_time($db, $dlid, time());
		$uc->unpause($id);
	}
	$_SESSION['setdata'] = array();
	unset ($_SESSION['dlsetname']) ;
	return $dlname;
}


function init_smarty($title)
{
	global $LN, $smarty;

	$smarty->assign('title', 		"{$LN['urdname']} - $title");
	$smarty->assign('heading', 		$title);
	$smarty->assign('menu',			generate_menu($LN));
	$challenge = set_challenge();
	$smarty->assign('challenge',    	$challenge);
}


function merge_sets(DatabaseConnection $db, $userID)
{
    $first_set = NULL;
    $other_sets = array();
    foreach ($_SESSION['setdata'] as $set) {
		$setid = $set['setid'];
		$type = $set['type'];
        if ($type == 'group') {
            if ($first_set === NULL)
                $first_set = $setid;
            else
                $other_sets[] = $setid;
        }
    }
    if (count($other_sets) == 0)
        return 'Needs more than one set';
	global $LN;
	$rprefs = load_config($db);
	$uc = new urdd_client($rprefs['urdd_host'], $rprefs['urdd_port'], $userID);

	if (!$uc->is_connected()) 
		throw new exception($LN['error_urddconnect']);

    $uc->merge_sets($first_set, $other_sets);
    $uc->disconnect();
    return '';
}


function process_which_button(DatabaseConnection $db, $userID, $type, $groupID /* or feedid*/, &$__message)
{
	global $LN;
	$message = '';
	$whichbutton = isset($_REQUEST['whichbutton']) ? $_REQUEST['whichbutton'] : '';
	// remove interesting marking from all sets on page
	if ($whichbutton == 'unmark_int_all' && isset($_POST['set_ids'])) {
		verify_challenge($_POST['challenge']);
		if ($groupID == 0)
			$_groupID = NULL;
		else 
			$_groupID = $groupID;
		unmark_all2($db, $userID, $_POST['set_ids'], 'statusint', $_groupID, $type, MARKING_OFF, TRUE);
	}
    if ($whichbutton == 'wipe_all' && isset($_POST['set_ids'])) {
        verify_challenge($_POST['challenge']);
		wipe_sets($db, $_POST['set_ids'], $type, $userID);
    }
	// mark all sets as not deleted on page
	if ($whichbutton == 'unmark_kill_all' && isset($_POST['set_ids'])) {
		verify_challenge($_POST['challenge']);
		if ($groupID == 0)
			$_groupID = NULL;
		else 
			$_groupID = $groupID;

		unmark_all2($db, $userID, $_POST['set_ids'], 'statuskill', $_groupID, $type, MARKING_OFF, TRUE);
	}
	// mark all sets as deleted on page
	if ($whichbutton == 'mark_kill_all' && isset($_POST['set_ids'])) {
		verify_challenge($_POST['challenge']);
		if ($groupID == 0)
			$_groupID = NULL;
		else 
			$_groupID = $groupID;
		$skip_int = (bool) get_pref($db, 'skip_int', $userID, 0);
		mark_all2($db, $userID, $_POST['set_ids'], 'statuskill', $_groupID,  $type, MARKING_ON, TRUE, $skip_int);
	}

	/* Create NZB */
	if ($whichbutton == 'getnzb' && count($_SESSION['setdata']) > 0) {
		verify_challenge($_POST['challenge']);
		try {
			$dlname = create_nzb($db, $userID);
			$message = $LN['NZB_created'] . ': "' . $dlname. '"';
		} catch (exception $e) {
			$__message[] = $e->getmessage();
		}
	}

	/* Download via Urdd */
	if ($whichbutton == 'urddownload' && count($_SESSION['setdata']) > 0) {
		verify_challenge($_POST['challenge']);
		try {
			$message = create_download($db, $userID);
			// Connect to Urdd:
		} catch (exception $e) {
			$__message[] = $e->getmessage();
		}
	}
    if ($whichbutton == 'mergesets' && count($_SESSION['setdata']) > 0) {
        verify_challenge($_POST['challenge']);
        try {
            merge_sets($db, $userID);
            $_SESSION['setdata'] = array();
            unset ($_SESSION['dlsetname']) ;
		} catch (exception $e) {
			$__message[] = $e->getmessage();
		}
    }

	/* Clear list? */
	if ($whichbutton == 'clearnzb') {
		verify_challenge($_POST['challenge']);
		$_SESSION['setdata'] = array();
		unset ($_SESSION['dlsetname']) ;
	}
	return $message;
}


function wipe_sets(DatabaseConnection $db, array $setids, $type, $userID)
{
    global $LN;
    $skip_int = (bool) get_pref($db, 'skip_int', $userID, 0);
    if ($skip_int) {
        $sets_str = '';
        foreach($setids as $set) {
            $db->escape($set, TRUE);
            $sets_str .=  "$set, ";
        }
        $sets_str = rtrim($sets_str, ', ');
    }

    if ($type == USERSETTYPE_GROUP) {
        $prefs = load_config($db);
        $uc = new urdd_client($prefs['urdd_host'], $prefs['urdd_port'], $userID);
        if ($uc->is_connected() === FALSE) 
            throw new exception($LN['error_urddconnect']);
        if ($skip_int) {
            $qry = "SELECT DISTINCT setdata.\"ID\" FROM setdata LEFT JOIN usersetinfo AS usi ON usi.\"setID\" = setdata.\"ID\" AND "
                . "usi.\"type\"='$type' WHERE setdata.\"ID\" IN ($sets_str) AND (usi.\"statusint\" <> " . MARKING_ON . " OR usi.\"statusint\" IS NULL)";
            $res = $db->execute_query($qry);
            if ($res === FALSE) 
                return;
            $setids = array();
            foreach ($res as $r) {
                $setids[] = $r['ID'];
            }
        }
        
        $uc->delete_set($setids);
        $uc->disconnect();
    } elseif ($type == USERSETTYPE_RSS) {
        $prefs = load_config($db);
        $uc = new urdd_client($prefs['urdd_host'], $prefs['urdd_port'], $userID);
        if ($uc->is_connected() === FALSE) 
            throw new exception($LN['error_urddconnect']);
        if ($skip_int) {
            $qry = "SELECT DISTINCT rss_sets.\"setid\" FROM rss_sets LEFT JOIN usersetinfo AS usi ON usi.\"setID\" = rss_sets.\"ID\" "
                . "AND \"type\"='$type' WHERE rss_sets.\"setID\" IN ($sets_str) AND usi.\"statusint\" <> " . MARKING_ON . " OR usi.\"statusint\" IS NULL)";
            $res = $db->execute_query($qry);
            if ($res === FALSE) 
                return;

            $setids = array();
            foreach ($res as $r) {
                $setids[] = $r['ID'];
            }
        }

        $uc->delete_set_rss($setids);
        $uc->disconnect();
    } else {
        throw new exception ('Unknown type');
    }
}

function get_total_rss_sets(DatabaseConnection $db)
{
	$res = $db->execute_query('SELECT COUNT("id") AS cnt FROM rss_sets');
	$totbin = $res[0]['cnt'];
	return $totbin;
}


function get_total_ng_sets(DatabaseConnection $db)
{
	$res = $db->execute_query('SELECT COUNT("ID") AS cnt FROM setdata');
	$totbin = $res[0]['cnt'];
	return $totbin;
}


function get_minsetsize_feed(DatabaseConnection $db, $feed_id, $userID, $default=0)
{
	$db->escape($feed_id, TRUE);
	$db->escape($userID, TRUE);
	$qry = "\"minsetsize\" FROM userfeedinfo WHERE \"feedid\"=$feed_id AND \"userid\"=$userID UNION SELECT $default";
	$res = $db->select_query($qry, 1);
	if ($res === FALSE)
		$minsetsize = $default;
	else 
		$minsetsize = $res[0]['minsetsize'];
	return $minsetsize;
}


function get_minsetsize_group(DatabaseConnection $db, $group_id, $userID, $default=0)
{
	$db->escape($group_id, TRUE);
	$db->escape($userID, TRUE);
	$qry = "\"minsetsize\" FROM usergroupinfo WHERE \"groupid\"=$group_id AND \"userid\"=$userID UNION SELECT $default";
	$res = $db->select_query($qry, 1);
	if ($res === FALSE)
		$minsetsize = $default;
	else 
		$minsetsize = $res[0]['minsetsize'];
	return $minsetsize;
}


function get_setname_group(DatabaseConnection $db, $setid)
{
	$db->escape($setid, TRUE);
	$res = $db->execute_query("SELECT \"subject\" FROM setdata where \"ID\" = $setid");
	$setname = $res[0]['subject'];
	return $setname;
}


function die_html($msg)
{
	echo trim(strip_tags($msg)); 
	die;
}


function get_set_info(DatabaseConnection $db, $setID, $origin_type)
{
	if ($origin_type == USERSETTYPE_GROUP)
		$sql = "* FROM setdata WHERE \"ID\" = '$setID'";
	else if ($origin_type == USERSETTYPE_RSS)
		$sql = "* FROM rss_sets WHERE \"setid\" = '$setID'";

	$res = $db->select_query($sql, 1);
	if ($res === FALSE) 
		die('could not find ' . $setID);
	
	if ($origin_type == USERSETTYPE_GROUP) {
		$originalsetname = strtolower($res[0]['subject']); // Only 1 row should be returned.
		$groupname = group_name($db, $res[0]['groupID']);
	} else if ($origin_type == USERSETTYPE_RSS) {
		$originalsetname = strtolower($res[0]['setname']); // Only 1 row should be returned.
		$groupname = feed_name($db, $res[0]['rss_id']);
	}
	return array(utf8_decode($originalsetname), $groupname);
}


function guess_set_type(DatabaseConnection $db, $setID, $groupname, $originalsetname)
{
	$result = array();
	$result[SETTYPE_MOVIE] = 0;
	$result[SETTYPE_TVSERIES] = 0;
	$result[SETTYPE_ALBUM] = 0;
	$result[SETTYPE_IMAGE] = 0;
	$result[SETTYPE_SOFTWARE] = 0;
	$result[SETTYPE_EBOOK] = 0;
	$result[SETTYPE_GAME] = 0;
	$result[SETTYPE_DOCUMENTARY] = 0;
	$result[SETTYPE_TVSHOW] = 0;

	// Check the groupname for hints:
	$bintype = '';
	$type = array();
	$type[SETTYPE_MOVIE] = array('movie', 'hdtv', 'xvid', 'divx', 'multimedia', 'dvd', 'vcd');
	$type[SETTYPE_TVSERIES] = array('movie', 'hdtv', 'xvid', 'divx', 'multimedia', 'dvd', 'vcd', 'tvseries', '.tv');
	$type[SETTYPE_ALBUM] = array('mp3', 'album', 'music', 'sounds', 'metal', 'rock', 'trance', 'dance');
	$type[SETTYPE_IMAGE] = array('images', 'pictures');
	$type[SETTYPE_SOFTWARE] = array('.x', '.core', 'boneless', 'warez', 'osx');
	$type[SETTYPE_EBOOK] = array('ebook', 'e-book');
	$type[SETTYPE_GAME] = array('game', 'xbox', 'playstation', 'wii', 'nintendo', 'ps3', 'ps2');
	$type[SETTYPE_DOCUMENTARY] = array('documentary', 'documentaries', 'reportages');
	$type[SETTYPE_TVSHOW] = array('xvid', 'divx', '.tv');

	foreach ($type as $bintype => $binarray)
		foreach ($binarray as $groupstring)
			if (stripos($groupname, $groupstring) !== FALSE) 
				$result[$bintype]++;

	// Check the setname for tell-tale signs:
	// And store matches so we can use them for filling in data later on:
	unset($type);
	$type = array();
	$match = array();
	$type[SETTYPE_MOVIE] = array('.avi', '.mkv', '.mpg', '.mov', 'xvid', 'divx', '720p', '1080i', '1080p', 'bluray', 'blu-ray', 'bd5', 'bd9', 'x264', 'dts', 'ac3', 'vhs');
	$type[SETTYPE_TVSERIES] = array('.avi', '.mkv', '.mpg', '.mov', 'xvid', 'divx', '720p', '1080i', '1080p', 'hdtv', 'season', 'dts', 'bd5', 'bd9', 'ac3');
	$type[SETTYPE_ALBUM] = array('.mp3', '.m3u', '.flac', '.wma', '.ogg', '.ape');
	$type[SETTYPE_IMAGE] = array('.jpg', '.png', '.gif', '.bmp', '.jpeg', '.tiff');
	$type[SETTYPE_SOFTWARE] = array('.iso', '.nrg', '.zip', 'osx');
	$type[SETTYPE_EBOOK] = array('.pdf', '.prc', '.kml', 'ebook', 'e-book', 'magazine', 'isbn');
	$type[SETTYPE_GAME] = array('.iso', 'xbox', 'playstation', 'wii');
	$type[SETTYPE_DOCUMENTARY] = array('.avi', '.mkv', '.mpg', '.mov', 'xvid', 'divx', '720p', '1080i', '1080p', 'hdtv', );
	$type[SETTYPE_TVSHOW] = array('.avi', '.mkv', '.mpg', '.mov', 'xvid', 'divx', '720p', '1080i', '1080p', 'hdtv');

	foreach ($type as $bintype => $binarray) {
		foreach ($binarray as $setstring) {
			if (stripos($originalsetname, $setstring) !== FALSE) {
				$result[$bintype]++;
				$match[$setstring] = TRUE;
			}
		}
	}

	// Adding an extra series-check by looking for sXXeXX strings:
	if (preg_match('/s([0-9]{1,2})[._ ]{0,1}e([0-9]{1,2})/i', $originalsetname, $prmatch)) {
		$result[SETTYPE_TVSERIES] += 5;
		$match['episode'] = 's' . $prmatch[1] . 'e' . $prmatch[2];
	} elseif (preg_match('/[^a-z0-9]([0-9]{1,2})x([0-9]{2})[^0-9]/i', $originalsetname, $prmatch)) {
		$result[SETTYPE_TVSERIES] += 4;
		$match['episode'] = 's' . $prmatch[1] . 'e' . $prmatch[2];
	} elseif (preg_match('/s([0-9]{1,2})[._ ]{0,1}d([0-9]{1,2})/i', $originalsetname, $prmatch)) {
		$result[SETTYPE_TVSERIES] += 4;
		$match['episode'] = 's' . $prmatch[1] . 'd' . $prmatch[2];
	} else {
		// If there's no episode thing, it's probably not a series or tvshow
		$result[SETTYPE_TVSERIES] -= 2;
	}

	// Look for year info, probably a movie or album then:
	if (preg_match('/[^0-9](19[0-9]{2}|20[012][0-9])[^0-9]/', $originalsetname, $prmatch)) {
		$result[SETTYPE_MOVIE] += 2;
		$result[SETTYPE_ALBUM] += 2;
		$match['year'] = $prmatch[1];
	}
	// Does it have a YYYYxMMxDD string or DDxMMxYYYY string?
	if (preg_match('/[^0-9](19[0-9]{2}|20[012][0-9])[^0-9]([0-9]{1,2})[^0-9]([0-9]{1,2})[^0-9]/', $originalsetname, $prmatch)) {
		$result[SETTYPE_TVSHOW] += 8;

		// Trim leading 0's:
		$cleanprmatch[] = array();
		foreach ($prmatch as $key => $mitem)
			$cleanprmatch[$key] = ((int) $mitem < 10 ? '0' : '') . (int) $mitem;

		$match['episode'] = $cleanprmatch[3] . '-' . $cleanprmatch[2] . '-' . $cleanprmatch[1];
	}elseif (preg_match('/[^0-9]([0-9]{1,2})[^0-9]([0-9]{1,2})[^0-9](19[0-9]{2}|20[012][0-9])/', $originalsetname, $prmatch)) {
		$result[SETTYPE_TVSHOW] += 8;

		// Trim leading 0's:
		$cleanprmatch[] = array();
		foreach ($prmatch as $key => $mitem)
			$cleanprmatch[$key] = ((int) $mitem < 10 ? '0' : '') . (int) $mitem;

		$match['episode'] = $cleanprmatch[1] . '-' . $cleanprmatch[2] . '-' . $prmatch[3];
	} else
		$result[SETTYPE_TVSHOW] -= 1;

	// Process by assuming the highest result is the right binarytype:
	arsort($result);
    list($key, $val) = each($result);
	return array($key, $val, $match);
}


function guess_more_data($val, $key, $newsetname, $groupname, array $match, array &$save)
{
	if ($val !== 0) {// If we don't know the filetype, we only set the name.
		switch ($key) {
		case SETTYPE_MOVIE:
			if (isset($match['720p']))	$save['quality'] = '9';
			if (isset($match['1080i']))	$save['quality'] = '9.5';
			if (isset($match['1080p']))	$save['quality'] = '10';
			if (isset($match['bluray']))	$save['movieformat'] = 'bluray';
			if (isset($match['blu-ray']))	$save['movieformat'] = 'bluray';
			if (isset($match['720p']))	$save['movieformat'] = '720p';
			if (isset($match['1080i']))	$save['movieformat'] = '1080i';
			if (isset($match['1080p']))	$save['movieformat'] = '1080p';
			if (isset($match['.avi']))	$save['movieformat'] = 'avi';
			if (isset($match['xvid']))	$save['movieformat'] = 'xvid';
			if (isset($match['divx']))	$save['movieformat'] = 'divx';
			if (isset($match['vhs']))	$save['movieformat'] = 'vhs';
			if (isset($match['.mpg']))	$save['movieformat'] = 'mpg';
			if (isset($match['.mov']))	$save['movieformat'] = 'mov';
			if (isset($match['bd5']))	$save['movieformat'] = 'bluray';
			if (isset($match['bd9']))	$save['movieformat'] = 'bluray';
			if (isset($match['dts']))	$save['audioformat'] = 'DTS';
			if (isset($match['ac3']))	$save['audioformat'] = 'Dolby Digital';
			if (isset($match['year']))	$save['year'] = $match['year'];
			break;
		case SETTYPE_TVSERIES:
			if (isset($match['720p']))	$save['quality'] = '9';
			if (isset($match['1080i']))	$save['quality'] = '9.5';
			if (isset($match['1080p']))	$save['quality'] = '10';
			if (isset($match['bluray']))	$save['movieformat'] = 'bluray';
			if (isset($match['blu-ray']))	$save['movieformat'] = 'bluray';
			if (isset($match['720p']))	$save['movieformat'] = '720p';
			if (isset($match['1080i']))	$save['movieformat'] = '1080i';
			if (isset($match['1080p']))	$save['movieformat'] = '1080p';
			if (isset($match['.avi']))	$save['movieformat'] = 'avi';
			if (isset($match['xvid']))	$save['movieformat'] = 'xvid';
			if (isset($match['divx']))	$save['movieformat'] = 'divx';
			if (isset($match['.mpg']))	$save['movieformat'] = 'mpg';
			if (isset($match['.mov']))	$save['movieformat'] = 'mov';
			if (isset($match['bd5']))	$save['movieformat'] = 'bluray';
			if (isset($match['bd9']))	$save['movieformat'] = 'bluray';
			if (isset($match['dts']))	$save['audioformat'] = 'DTS';
			if (isset($match['episode']))	$save['episode'] = $match['episode'];
			break;
		case SETTYPE_ALBUM:
			if (isset($match['.mp3']))	$save['musicformat'] = 'mp3';
			if (isset($match['.m3u']))	$save['musicformat'] = 'mp3';
			if (isset($match['.flac']))	$save['musicformat'] = 'flac';
			if (isset($match['.wma']))	$save['musicformat'] = 'wma';
			if (isset($match['.ogg']))	$save['musicformat'] = 'ogg';
			if (isset($match['.ape']))	$save['musicformat'] = 'ape';
			if (isset($match['year']))	$save['year'] = $match['year'];
			break;
		case SETTYPE_TVSHOW:
			if (isset($match['720p']))	$save['quality'] = '9';
			if (isset($match['1080i']))	$save['quality'] = '9.5';
			if (isset($match['1080p']))	$save['quality'] = '10';
			if (isset($match['bluray']))	$save['movieformat'] = 'bluray';
			if (isset($match['blu-ray']))	$save['movieformat'] = 'bluray';
			if (isset($match['720p']))	$save['movieformat'] = '720p';
			if (isset($match['1080i']))	$save['movieformat'] = '1080i';
			if (isset($match['1080p']))	$save['movieformat'] = '1080p';
			if (isset($match['.avi']))	$save['movieformat'] = 'avi';
			if (isset($match['xvid']))	$save['movieformat'] = 'xvid';
			if (isset($match['divx']))	$save['movieformat'] = 'divx';
			if (isset($match['.mpg']))	$save['movieformat'] = 'mpg';
			if (isset($match['.mov']))	$save['movieformat'] = 'mov';
			if (isset($match['bd5']))	$save['movieformat'] = 'bluray';
			if (isset($match['bd9']))	$save['movieformat'] = 'bluray';
			if (isset($match['dts']))	$save['audioformat'] = 'DTS';
			if (isset($match['episode']))	$save['episode'] = $match['episode'];
			break;
		case SETTYPE_IMAGE:
		case SETTYPE_EBOOK:
		case SETTYPE_GAME:
		case SETTYPE_DOCUMENTARY:
		case SETTYPE_SOFTWARE:
			break;
		}

		// Set the binarytype:
		$save['binarytype'] = $key;
	} 
	if ($newsetname != '') {
		// Here's where HAL comes in.
		// Setname probably has underscores or periods that should be replaced by blanks:
		$newsetname = str_replace('.', ' ', $newsetname);	
		$newsetname = str_replace('_', ' ', $newsetname);	

		// Save the new setname:
		$save['name'] = trim($newsetname, "- \x0b\n\t\0\r");
	}

	$is_xrated = array('erotic', 'sex', 'nude', 'porn', 'gay', 'xxx');
	foreach($is_xrated as $str)
		if (stripos($groupname, $str) !== FALSE)
			$save['xrated'] = 1;
}


function save_extsetinfo(DatabaseConnection $db, $setID, $userID, array $namevalues, $type, $overwrite = TRUE)
{
	assert (is_numeric($userID) && is_bool($overwrite));
	if (!is_seteditor($db, $userID))
		die('You have no permission to do this!');

	// Save changes:
	$db->escape($setID);

	$newsetname = generate_set_name($db, $namevalues);
	$unsafensn = $newsetname;
	$db->escape($newsetname, TRUE);
	foreach ($namevalues as $name => $value_x) {
		$value = (trim($value_x));
		$fieldEmpty = ($value == ''); // Empty field?

		// Does info exist?
		$sql = " * FROM extsetdata WHERE \"setID\" = '$setID' AND \"name\" = '$name' AND \"type\" = '$type'";
		$res = $db->select_query($sql);
		// Check if the field was empty, and if the stored field exists

		if ($res === FALSE && !$fieldEmpty) {
			// New data:
			$db->insert_query('extsetdata', array('setID', 'name', 'value', 'committed', 'type'), array($setID, $name, $value, ESI_NOT_COMMITTED, $type) );
		} elseif ($res !== FALSE && ($overwrite === TRUE || (isset($res[0]['value']) && trim($res[0]['value']) == ''))) {
			// OK, something existed:

			$db->escape($value);
			$db->escape($name);
			$sql = "UPDATE extsetdata SET \"value\" = '$value', \"committed\" = '" . ESI_NOT_COMMITTED . "' WHERE \"setID\" = '$setID' AND \"name\" = '$name' AND \"type\" = '$type'";
			$db->execute_query($sql);
		} elseif ($res !== FALSE && $overwrite === FALSE) {
			// skip it but set the value in the array to the original value
			if (isset($res[0][$name]))
				$namevalues[ $res[0][$name] ] = utf8_decode($res[0]['value']);
		}
	}
	// Update setname:

	$sql = " * FROM extsetdata WHERE \"setID\" = '$setID' AND \"name\" = 'setname' AND \"type\" = '$type'";
	$res = $db->select_query($sql);
	if ($res === FALSE) {
		$sql = "INSERT INTO extsetdata (\"setID\", \"name\", \"value\", \"committed\", \"type\") VALUES ('$setID', 'setname', $newsetname, 0, $type)";
	} else {
		$sql = "UPDATE extsetdata SET \"value\" = $newsetname WHERE \"setID\" = '$setID' AND \"name\" = 'setname' AND \"type\" = '$type'";
	}
	$db->execute_query($sql);
	return $unsafensn;
}


function load_language($lang)
{
    global $smarty, $LN, $DONOT_SMARTIFY;

    if (isset($LN))
        unset($LN);

    $pathsl = realpath(dirname(__FILE__));

    if ($lang === NULL || !is_file("$pathsl/lang/$lang")){
        require "$pathsl/lang/" . DEFAULT_LANGUAGE;
    } else {
        require "$pathsl/lang/$lang";
    }
}


function set_post_status()
{
	$_SESSION['post_hide_status'] = array(
	'global' => 0,
	'ready' => 0,
	'finished' => 0,
	'active' => 0,
	'paused' => 0,
	'stopped' => 0,
	'shutdown' => 0,
	'error' => 0,
	'complete' => 0,
	'rarfailed' => 0,
	'par2failed' => 0,
	'yyencodefailed' => 0,
	'queued' => 0,
	'rarred' => 0,
	'par2ed' => 0,
	'yyencoded' => 0,
    'cancelled' => 0
);
}
function set_down_status()
{
    $_SESSION['transfer_hide_status'] = array(
	'global' => 0,
	'ready' => 0,
	'finished' => 0,
	'active' => 0,
	'paused' => 0,
	'stopped' => 0,
	'shutdown' => 0,
	'error' => 0,
	'complete' => 0,
	'rarfailed' => 0,
	'par2failed' => 0,
	'cksfvfailed' => 0,
	'queued' => 0,
	'dlfailed' => 0,
    'cancelled' => 0
);
}

?>
